﻿using LiteBlog.Components.Contracts;
using LiteBlog.Components.Enums;
using LiteBlog.Controllers.Contracts;
using LiteBlog.Models;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace LiteBlog.Controllers.Tests
{
    [TestClass]
    public class AdminControllerTests : ControllerTests<IAdminController>
    {
        private static readonly string UserName = "admin";
        private static readonly string Password = "password";
        private static readonly string NewPassword = "newpassword";

        [TestMethod]
        public void LoginValidatesCredentials()
        {
            var loginModel = new LoginModel(UserName, Password);
            var mock = Mock.Get<IAuthorComp>(_controller.AuthorComponent);
            mock.Setup(a => a.ValidateUser(It.IsAny<string>(), It.IsAny<string>())).Returns(MethodResult.LoginFailure);
            _controller.Login(loginModel);
            mock.Verify(a => a.ValidateUser(UserName, Password));
        }

        [TestMethod]
        public void LoginSignsInIfCredentialsAreValid()
        {
            var loginModel = new LoginModel(UserName, Password);
            var authorMock = Mock.Get<IAuthorComp>(_controller.AuthorComponent);
            authorMock.Setup(a => a.ValidateUser(It.IsAny<string>(), It.IsAny<string>())).Returns(MethodResult.LoginSuccess);
            _controller.Login(loginModel);
            var mock = Mock.Get<IAuthenticationHelper>(_controller.AuthenticationHelper);
            mock.Verify(a => a.SignIn(UserName));
        }

        [TestMethod]
        public void LoginDoesNotSignInIfCredentialsAreInvalid()
        {
            var loginModel = new LoginModel(UserName, Password);
            var authorMock = Mock.Get<IAuthorComp>(_controller.AuthorComponent);
            authorMock.Setup(a => a.ValidateUser(It.IsAny<string>(), It.IsAny<string>())).Returns(MethodResult.LoginFailure);
            _controller.Login(loginModel);
            var mock = Mock.Get<IAuthenticationHelper>(_controller.AuthenticationHelper);
            mock.Verify(a => a.SignIn(It.IsAny<string>()), Times.Never);
        }


        [TestMethod]
        public void LogoutWorks()
        {
            _controller.Logout();
            var mock = Mock.Get<IAuthenticationHelper>(_controller.AuthenticationHelper);
            mock.Verify(a => a.SignOut());
        }

        [TestMethod]
        public void MenuIsValid()
        {
            var actionResult = _controller.Menu();
            Assert.IsInstanceOfType(actionResult, typeof(PartialViewResult));
        }

        [TestMethod]
        public void ChangePasswordIsValid()
        {
            var actionResult = _controller.ChangePassword();
            Assert.IsInstanceOfType(actionResult, typeof(ViewResult));
        }

        [TestMethod]
        public void ChangePasswordValidatesCredentials()
        {
            var model = new ChangePasswordModel(UserName, Password, NewPassword, NewPassword);
            var mock = Mock.Get<IAuthorComp>(_controller.AuthorComponent);
            mock.Setup(a => a.ValidateUser(It.IsAny<string>(), It.IsAny<string>())).Returns(MethodResult.LoginFailure);
            _controller.ChangePassword(model);
            mock.Verify(a => a.ValidateUser(UserName, Password));
        }

        [TestMethod]
        public void ChangePasswordWorks()
        {
            var model = new ChangePasswordModel(UserName, Password, NewPassword, NewPassword);
            var mock = Mock.Get<IAuthorComp>(_controller.AuthorComponent);
            mock.Setup(a => a.ValidateUser(It.IsAny<string>(), It.IsAny<string>())).Returns(MethodResult.LoginSuccess);
            mock.Setup(a => a.ChangePassword(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(MethodResult.ChangePasswordSuccess);
            _controller.ChangePassword(model);
            mock.Verify(a => a.ChangePassword(UserName, Password, NewPassword));
        }
    }
}
